﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Dynamic;
using System.Web.Mvc;
using Xenta.Attributes;
using Xenta.Utils;
using Xenta.Web.Controllers;

namespace Xenta.Web.Areas.Wizard.Controllers
{
    [Authenticate]
    public sealed class ForumPostController : ExtController
    {
        [HttpGet, RestoreState]
        public ActionResult Create(int topicID, int? parentID)
        {
            dynamic m = new ExpandoObject();

            m.Topic = Svc.ProcessOperation("GetForumTopic", new
            {
                EntityID = topicID
            }, new
            {
                DisclosureLevel = "Entire"
            });
            if(m.Topic == null)
                return HttpNotFound();

            m.Post = null;
            m.Parent = null;
            if(parentID.HasValue)
            {
                m.Parent = Svc.ProcessOperation("GetForumPost", new
                {
                    EntityID = parentID.Value
                }, new
                {
                    DisclosureLevel = "Entire"
                });
            }
            return View(m);
        }

        [HttpPost, PersistState, ValidateInput(false)]
        public ActionResult Create(int topicID, int parentID, string text)
        {
            try
            {
                Svc.ProcessOperation("CreateForumPost", new
                {
                    MemberID = JDM.Int32(Svc.ForumMember.EntityID),
                    ParentID = parentID,
                    TopicID = topicID,
                    Text = text,
                    Flags = "Active"
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(ModelState.IsValid
                ? Loc.Act("Show").Ctrl("Topic").Area("Forum").Set(new
                {
                    id = topicID,
                    page = -1
                }).Localized() 
                : Loc.Act("Create").Set(new
                {
                    topicID
                }).Localized());
        }

        [HttpGet, RestoreState]
        public ActionResult Edit(int id)
        {
            dynamic m = new ExpandoObject();

            m.Post = Svc.ProcessOperation("GetForumPost", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Entire"
            });
            if(m.Post == null)
                return HttpNotFound();

            m.Topic = Svc.ProcessOperation("GetForumTopic", new
            {
                EntityID = JDM.Int32(m.Post.Topic.EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            m.Forum = Svc.ProcessOperation("GetForum", new
            {
                EntityID = JDM.Int32(m.Topic.Forum.EntityID)
            }, new
            {
                DisclosureLevel = "Entire",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });

            var acl = m.Forum.AccessRules as IEnumerable<dynamic>;
            m.UserCanModerate = acl.Where(x => Svc.InRole((string)JDM.String(x.Role.Code)))
                .Any(x => JDM.String(x.AccessRights).Contains("Moderate"));
            if(JDM.Int32(m.Post.Member.EntityID) != JDM.Int32(Svc.ForumMember.EntityID) &&
                !m.UserCanModerate)
            {
                return new HttpUnauthorizedResult();
            }
            return View(m);
        }

        [HttpPost, PersistState, ValidateInput(false)]
        public ActionResult Update(int id, string text)
        {
            var post = Svc.ProcessOperation("GetForumPost", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base"
            });
            if(post == null)
                return HttpNotFound();

            try
            {
                Svc.ProcessOperation("UpdateForumPost", new
                {
                    EntityID = id,
                    Text = text,
                    Flags = JDM.String(post.Flags)
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(ModelState.IsValid
                ? Loc.Act("Show").Ctrl("Topic").Area("Forum").Set(new
                {
                    id = JDM.Int32(post.Topic.EntityID)
                }).Localized()
                : Loc.Act("Edit").Set(new
                {
                    id
                }).Localized());
        }

        [HttpPost, PersistState, ValidateInput(false)]
        public ActionResult Moderate(int id, string text, string[] flags)
        {
            var post = Svc.ProcessOperation("GetForumPost", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base"
            });
            if(post == null)
                return HttpNotFound();

            var topic = Svc.ProcessOperation("GetForumTopic", new
            {
                EntityID = JDM.Int32(post.Topic.EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            var forum = Svc.ProcessOperation("GetForum", new
            {
                EntityID = JDM.Int32(topic.Forum.EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            
            var acl = forum.AccessRules as IEnumerable<dynamic>;
            if(!acl.Where(x => Svc.InRole((string)JDM.String(x.Role.Code)))
                .Any(x => JDM.String(x.AccessRights).Contains("Moderate")))
            {
                return new HttpUnauthorizedResult();
            }

            try
            {
                Svc.ProcessOperation("UpdateForumPost", new
                {
                    EntityID = id,
                    Text = text,
                    Flags = flags.Merge(",")
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(ModelState.IsValid
                ? Loc.Act("Show").Ctrl("Topic").Set(new
                {
                    id = JDM.Int32(post.Topic.EntityID)
                }).Localized()
                : Loc.Act("Edit").Set(new
                {
                    id
                }).Localized());
        }

        [HttpGet, PersistState]
        public ActionResult Delete(int id)
        {
            var post = Svc.ProcessOperation("GetForumPost", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base"
            });
            if(post == null)
                return HttpNotFound();

            try
            {
                Svc.ProcessOperation("DeleteForumPost", new
                {
                    EntityID = id
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }

            return RedirectToAction(ModelState.IsValid
                ? Loc.Act("Show").Ctrl("Topic").Set(new
                {
                    id = JDM.Int32(post.Topic.EntityID)
                }).Localized()
                : Loc.Act("Edit").Set(new
                {
                    id
                }).Localized());
        }

        [HttpGet, PersistState]
        public ActionResult MarkUseful(int id)
        {
            var post = Svc.ProcessOperation("GetForumPost", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base"
            });
            if(post == null)
                return HttpNotFound();

            try
            {
                Svc.ProcessOperation("MarkForumPostAsUseful", new
                {
                    EntityID = id
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Show").Ctrl("Topic").Area("Forum").Set(new
            {
                id = JDM.Int32(post.Topic.EntityID)
            }).Localized());
        }

        [HttpGet, PersistState]
        public ActionResult MarkUseless(int id)
        {
            var post = Svc.ProcessOperation("GetForumPost", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base"
            });
            if(post == null)
                return HttpNotFound();

            try
            {
                Svc.ProcessOperation("MarkForumPostAsUseless", new
                {
                    EntityID = id
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Show").Ctrl("Topic").Area("Forum").Set(new
            {
                id = JDM.Int32(post.Topic.EntityID)
            }).Localized());

        }
    }
}
